package ElectricCraft.frames;

import ElectricCraft.drawer.Drawer;
import ElectricCraft.misc.Util;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

/**
 * PathPane class.
 */
public class PathPane extends JPanel {
    public interface Path {
        String  getName(int index);
        int     size();
    }

    private static final int PATH_BUTTONS_COUNT = 8;

    private final JButton [] buttons;
    private final int [] buttonIndex;
    public PathPane() {
        super(new BorderLayout());

        Box pathBox = Box.createHorizontalBox();

        buttons = new JButton[PATH_BUTTONS_COUNT];
        for (int k = 0; k < PATH_BUTTONS_COUNT; ++k) {
            JButton button = Util.createBasicButton();
            button.setMargin(new Insets(0, 1, 0, 1));
            buttons[k] = button;

            final int index = k;
            button.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    if (buttonIndex[index] == -1) {
                        return ;
                    }

                    notifyPathChanged(currentPath, buttonIndex[index]);
                }
            });

            button.setVisible(false);
            pathBox.add(button);
        }

        pathBox.add(Box.createHorizontalGlue());

        buttonIndex = new int[PATH_BUTTONS_COUNT];
        Arrays.fill(buttonIndex, -1);

        add(pathBox, BorderLayout.CENTER);
    }

    @Override
    public void setBackground(Color color) {
        super.setBackground(color);

        if (buttons == null) {
            return ;
        }

        for (JButton button : buttons) {
            button.setBackground(color);
        }
    }

    private Path currentPath;
    public void setPath(Path path) {
        int count = (path != null) ? path.size() : 0;

        // insert '...' button only when path is too long (according to pane width)

        currentPath = path;

        if (count < PATH_BUTTONS_COUNT) {
            for (int k = 0; k < PATH_BUTTONS_COUNT; ++k) {
                if (k < count && path != null) {
                    String name = path.getName(k);

                    buttons[k].setText(k + 1 < count ? String.format("%s  >", name) : name);

                    buttonIndex[k] = k;
                    buttons[k].setVisible(true);
                } else {
                    buttonIndex[k] = -1;
                    buttons[k].setVisible(false);
                }
            }

            return ;
        }

        assert path != null;

        int lastIndex = count - 1;

        buttonIndex[0] = 0;
        buttons[0].setText(path.getName(0));

        buttonIndex[1] = -1;
        buttons[1].setText("...");

        final int restCount = PATH_BUTTONS_COUNT - 2;
        for (int k = 0; k < restCount; ++k) {
            buttonIndex[PATH_BUTTONS_COUNT - 1 - k] = lastIndex - k;

            String name = path.getName(lastIndex - k);
            buttons[PATH_BUTTONS_COUNT - 1 - k].setText(k != 0 ? String.format("%s  >", name) : name);
        }

        for (JButton button : buttons) {
            button.setVisible(true);
        }
    }

    private final Point buttonLocation = new Point();
    public void draw(Drawer drawer, Graphics gr) {
        for (JButton button : buttons) {
            if (button.isVisible()) {
                button.getLocation(buttonLocation);
                drawer.pushTransform(buttonLocation.x, buttonLocation.y);
                button.paint(gr);
                drawer.popTransform();
            }
        }
    }

    public interface PathChangedListener {
        void pathChanged(Path path, int index);
    }

    private final List<PathChangedListener> pathChangedListeners = new LinkedList<PathChangedListener>();
    public void addPathChangedListener(PathChangedListener listener) {
        pathChangedListeners.add(listener);
    }

    private void notifyPathChanged(Path path, int index) {
        for (PathChangedListener listener : pathChangedListeners) {
            listener.pathChanged(path, index);
        }
    }
}
